﻿// -------------------------------------------------------------------------
//    @FileName         :    NFSkillPart.cpp
//    @Author           :    gaoyi
//    @Date             :    24-8-29
//    @Email            :    445267987@qq.com
//    @Module           :    NFSkillPart
//
// -------------------------------------------------------------------------

#include "NFSkillPart.h"

#include <NFPlayer.h>
#include <NFSkillUtil.h>
#include <SkillDescEx.h>
#include <TransferDescEx.h>
#include <DescStore/TransferDesc.h>
#include <DescStore/SkillSlotDesc.h>
#include <DescStore/TransferTreeDesc.h>

#include "proto_db.pb.h"

NFSkillPart::NFSkillPart()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFSkillPart::~NFSkillPart()
{
}

int NFSkillPart::CreateInit()
{
    m_iSkillIndex = 0;
    return 0;
}

int NFSkillPart::ResumeInit()
{
    return 0;
}

int NFSkillPart::LoadFromDB(const proto_ff::tbRoleDetail *pDBData)
{
    CHECK_NULL(0, pDBData);
    m_stData.FromPb(pDBData->role_base_data().skill());
    m_stData2.FromPb(pDBData->role_base_data().skill_2());
    m_iSkillIndex = pDBData->role_base_data().skill_index();
    return 0;
}

int NFSkillPart::InitConfig(proto_ff::tbRoleDetail *pDbData, const RoleOne &stRoleOne)
{
    CHECK_NULL(0, pDbData);
    InitConfig(pDbData->mutable_role_base_data()->mutable_skill(), stRoleOne);
    InitConfig(pDbData->mutable_role_base_data()->mutable_skill_2(), stRoleOne);

    return 0;
}

int NFSkillPart::SaveDB(proto_ff::tbRoleDetail *pDBData)
{
    CHECK_NULL(0, pDBData);
    m_stData.ToPb(pDBData->mutable_role_base_data()->mutable_skill());
    m_stData2.ToPb(pDBData->mutable_role_base_data()->mutable_skill_2());
    pDBData->mutable_role_base_data()->set_skill_index(m_iSkillIndex);
    return 0;
}

int NFSkillPart::SaveRoleSimpleInfo(proto_ff::Proto_RoleSimpleInfo* pDbData)
{
    CHECK_NULL(0, pDbData);
    pDbData->set_transfer_id(GetTransferID());
    return 0;
}

int NFSkillPart::InitConfig(proto_ff::RoleSkillData *pRoleData, const RoleOne &stRoleOne)
{
    InitSkillSlot(pRoleData);

    //transfer skill
    auto pTransferDesc = TransferDesc::Instance()->GetDesc(stRoleOne.actor_id);
    CHECK_NULL(0, pTransferDesc);

    pRoleData->set_transfer_id(pTransferDesc->init_transfer_id);

    const TTransferLayerInfo *pLayerInfo = TransferDescEx::Instance()->GetTransferLayerInfo(pTransferDesc->init_transfer_id);
    CHECK_NULL(0, pLayerInfo);

    pRoleData->set_version(0);

    for (int i = 0; i < (int) pLayerInfo->m_aiAutoNodeID.size(); ++i)
    {
        auto pTreeDesc = TransferTreeDesc::Instance()->GetDesc(pLayerInfo->m_aiAutoNodeID[i]);
        CHECK_NULL(0, pTreeDesc);

        if (pTreeDesc->unlock_lv == 1)
        {
            proto_ff::HeroSkillInfo *pSkillInfo = pRoleData->add_learn_skill();
            MakeNewSkillInfo(pSkillInfo, pTreeDesc->type, pTreeDesc->skill_id);

            AttachSkillToSet1(pRoleData, (proto_ff::enSkillTalentType) pTreeDesc->type, pTreeDesc->skill_id);
        }
    }

    for (int i = 0; i < MAX_TREE_NODE_PER_LAYER; ++i)
    {
        int iTreeID = pLayerInfo->m_aiNodeID[0][i];
        if (iTreeID <= 0)
        {
            continue;
        }

        auto pTreeDesc = TransferTreeDesc::Instance()->GetDesc(iTreeID);
        if (pTreeDesc && pTreeDesc->need_lv_begin == 1)
        {
            proto_ff::HeroSkillInfo *pSkillInfo = pRoleData->add_learn_skill();
            MakeNewSkillInfo(pSkillInfo, pTreeDesc->type, pTreeDesc->skill_id);

            if (pTreeDesc->type == proto_ff::ESKILL_TALENT_TYPE_ACTIVE)
            {
                AttachSkillToSet1(pRoleData, (proto_ff::enSkillTalentType) pTreeDesc->type, pTreeDesc->skill_id);
            }
        }
    }

    //attach ex-skill
    MakeInitExSkillInfo(pRoleData, pTransferDesc);

    pRoleData->set_skill_point(0);
    pRoleData->set_use_set_idx(0);
    pRoleData->set_free_switch(true);
    pRoleData->set_is_awake(false);
    pRoleData->set_use_skill_point(0);
    pRoleData->set_ex_transfer_id(stRoleOne.ex_transfer_id);
    return 0;
}

int NFSkillPart::InitSkillSlot(proto_ff::RoleSkillData *pRoleData)
{
    CHECK_NULL(0, pRoleData);

    proto_ff::HeroSkillSet *pSkillSet1 = pRoleData->add_skill_set();

    for (int i = 0; i < MAX_SKILL_SLOT_DESC_NUM; ++i)
    {
        pSkillSet1->add_attach_skill(-1);
    }

    auto &vecDesc = SkillSlotDesc::Instance()->GetResDesc();
    for (size_t i = 0; i < vecDesc.size(); ++i)
    {
        auto pSlotDesc = &vecDesc[i];
        if (pSlotDesc->unlock_lv <= 1)
        {
            pSkillSet1->set_attach_skill(pSlotDesc->id - 1, 0);
        }
    }

    return 0;
}

int NFSkillPart::AttachSkillToSet1(proto_ff::RoleSkillData *pRoleData, proto_ff::enSkillTalentType eType, int iSkillId)
{
    proto_ff::HeroSkillSet *pSkillSet1 = pRoleData->mutable_skill_set(0);
    for (int i = 1; i <= MAX_SKILL_SLOT_DESC_NUM; ++i)
    {
        auto pSlotDesc = SkillSlotDesc::Instance()->GetDesc(i);
        CHECK_NULL(0, pSlotDesc);

        if (NFSkillUtil::IsSkillMatchSlot(eType, (proto_ff::enSkillSlotType) pSlotDesc->type)
            && pSkillSet1->attach_skill(i - 1) == 0)
        {
            pSkillSet1->set_attach_skill(i - 1, iSkillId);
            break;
        }
    }

    return 0;
}

int NFSkillPart::MakeNewSkillInfo(proto_ff::HeroSkillInfo *pSkillInfo, int iType, int iSkillId)
{
    CHECK_NULL(0, pSkillInfo);

    pSkillInfo->set_skill_id(iSkillId);
    pSkillInfo->set_type((proto_ff::enSkillTalentType) iType);
    pSkillInfo->set_is_talent(true);
    pSkillInfo->set_is_read(false);
    pSkillInfo->set_skill_lv(1);
    pSkillInfo->set_is_lock(false);

    return 0;
}

int NFSkillPart::MakeInitExSkillInfo(proto_ff::RoleSkillData *pRoleData, const E_Transfer *pTransferDesc)
{
    CHECK_NULL(0, pRoleData);
    CHECK_NULL(0, pTransferDesc);

    for (int i = 0; i < (int) pTransferDesc->pre_transfer_skill.size(); ++i)
    {
        if (pTransferDesc->pre_transfer_skill[i] > 0)
        {
            proto_ff::HeroSkillInfo *pSkillInfo = pRoleData->add_learn_skill();
            MakeNewSkillInfo(pSkillInfo, proto_ff::ESKILL_TALENT_TYPE_ACTIVE, pTransferDesc->pre_transfer_skill[i]);

            int iExSkillSlotIdx = SkillDescEx::Instance()->GetExSkillSlot(MAX_EX_SKILL_SLOT_NUM - i - 1);
            for (int k = 0; k < pRoleData->skill_set_size(); ++k)
            {
                if (IS_VALID_SKILL_SLOT(iExSkillSlotIdx + 1))
                {
                    pRoleData->mutable_skill_set(k)->set_attach_skill(iExSkillSlotIdx, pTransferDesc->pre_transfer_skill[i]);
                }
            }
        }
    }

    return 0;
}

int NFSkillPart::MakePlayerDataCS(proto_ff::Proto_CSGetRoleRsp* pGetRoleRsp)
{
    m_stData.ToPb(pGetRoleRsp->mutable_skill_data());
    m_stData2.ToPb(pGetRoleRsp->mutable_skill_2());
    pGetRoleRsp->set_skill_index(m_iSkillIndex);
    return 0;
}

int NFSkillPart::MakeCityPlayerData(proto_ff::CityRoleInfo* pCityRoleInfo)
{
    CHECK_NULL(0, pCityRoleInfo);
    pCityRoleInfo->set_transfer_id(GetTransferID());
    return 0;
}

bool NFSkillPart::IsTransfer() const
{
    auto pPlayer = GetPlayer();
    CHECK_NULL_RE_FALSE(0, pPlayer);

    auto pDesc = TransferDescEx::Instance()->GetDescByProf(pPlayer->GetProfession());
    if (pDesc && pDesc->init_transfer_id != m_stData.transfer_id)
    {
        return true;
    }
    return false;;
}

bool NFSkillPart::IsAwake() const
{
    return m_stData.is_awake;
}
